"""
Overall package info
"""
import socket
import Image
import md5

class Growl:
	"""
	Basic class info
	"""
	
	def __init__(self, app_name = "GNTPy", host = "localhost", port = 23053):
		self.app_name = app_name
		self.host = host
		self.port = port
		self.notifs = []
	
	def _send(self, data):
		"""
		Opens a socket to the target and sends data, returning the result
		"""
		sck = socket.socket()
		sck.connect((self.host, self.port))
		sck.send(data)
		return sck.recv(1024)

	def register(self, notifications):
		"""
		Registers the application with Growl
		"""
		if not isinstance(notifications, list):
			notifications = [notifications]
		
		images = {} # Will be used later for images

		data = "GNTP/1.0 REGISTER NONE\r\n"
		data += "Application-Name: %s\r\n" % (self.app_name)
		# data += "Application-Icon: "
		data += "Notifications-Count: %u\r\n" % (len(notifications))
		data += "\r\n"
		# Notification info
		for notif in notifications:
			if not isinstance(notif, dict):
				raise Exception("Notification is not a dictionary: %s" % repr(notif))
			if notif.has_key("name"):
				data += "Notification-Name: %s\r\n" % (notif["name"])
				self.notifs.append(notif["name"])
			else:
				raise Exception("Notification %s has no name" % repr(notif))
			if notif.has_key("display_name"):
				data += "Notification-Display-Name: %s\r\n" % (notif["display_name"])
			if notif.has_key("enabled"):
				data += "Notification-Enabled: %s\r\n" % (str(notif["enabled"]))
			if notif.has_key("icon"):
				# Let's see if the icon is a string or a PIL Image
				if str(notif["icon"])[:7].upper() == "HTTP://":
					# URL. Send as-is
					img_text = notif["icon"]
				else:
					if isinstance(notif["icon"], str):
						img = Image.open(notif["icon"])
					elif isinstance(notif["icon"], Image.Image):
						img = notif["icon"]
					else:
						raise Exception("Unknown image type for notification %s" % (notif["name"]))
					img_hash = md5.new(img.tostring()).hexdigest()
					img_text = "x-growl-resource://%s" % (img_hash)
					images[img_hash] = img.tostring()
				data += "Notification-Icon: %s\r\n" % (img_text)
			data += "\r\n"
		for img_hash, img_stream in images.iteritems():
			data += "Identifier: %s\r\n" % (img_hash)
			data += "Length: %u\r\n" % (len(img_stream))
			data += "\r\n"
			data += img_stream
			data += "\r\n"
		data += "\r\n"
		
		result = self._send(data)
		if "-ERROR" in result.split("\r\n")[0]:
			raise Exception("Unable to register")

	def notify(self, name, title, text = "", id = "", sticky = False, icon = "", priority = 0):
		"""
		Sends a notification.
		
		id is the unique id of the notification. The notifications system
		should replace currently active notifications with the same id with
		a newer one.

		name must be a valid name of a notification registered before.
		"""
		if name not in self.notifs:
			raise Exception("Unregistered notification '%s'" % name)
		data = "GNTP/1.0 NOTIFY NONE\r\n"
		data += "Application-Name: %s\r\n" % (self.app_name)
		data += "Notification-Name: %s\r\n" % (name)
		if id: data += "Notification-ID: %s\r\n" % (id)
		data += "Notification-Title: %s\r\n" % (title)
		if text: data += "Notification-Text: %s\r\n" % (text.replace("\r\n","\n"))
		if sticky: data += "Notification-Sticky: %s\r\n" % (str(sticky))
		if priority != 0: data += "Notification-Priority: %d\r\n" % (priority)
		if icon: data += "Notification-Icon: %s\r\n" % (icon)
		data += "\r\n"

		result = self._send(data)
		if "-ERROR" in result.split("\r\n")[0]:
			raise Exception("Unable to notify")
	
